home *** CD-ROM | disk | FTP | other *** search
Text File | 1975-04-26 | 24.7 KB | 1,233 lines |
- head 1.8;
- branch ;
- access ;
- symbols ;
- locks ;
- comment @@;
-
-
- 1.8
- date 92.03.01.10.27.08; author melling; state Exp;
- branches ;
- next 1.7;
-
- 1.7
- date 92.03.01.05.07.51; author melling; state Exp;
- branches ;
- next 1.6;
-
- 1.6
- date 92.02.29.20.35.58; author melling; state Exp;
- branches ;
- next 1.5;
-
- 1.5
- date 92.02.28.05.19.08; author melling; state Exp;
- branches ;
- next 1.4;
-
- 1.4
- date 91.12.19.10.12.51; author melling; state Exp;
- branches ;
- next 1.3;
-
- 1.3
- date 91.12.16.17.22.18; author melling; state Exp;
- branches ;
- next 1.2;
-
- 1.2
- date 91.12.07.07.49.23; author melling; state Exp;
- branches ;
- next 1.1;
-
- 1.1
- date 91.12.07.03.37.08; author melling; state Exp;
- branches ;
- next ;
-
-
- desc
- @Tetris 1.1
- @
-
-
- 1.8
- log
- @Release 1.3
- @
- text
- @#import <appkit/NXImage.h>
- #import <ctype.h>
- #import <dpsclient/wraps.h>
- #import <math.h>
- #import <appkit/graphics.h>
- #import "TetMatrix.h"
- #import "Piece.h"
- #import "ScoreKeeper.h"
- #import "TetApp.h"
- #import "wraps.h"
-
- // The number of pixels a block moves every step
- // Make it a divisor of the block size
- static const float ANM_DELTA = 8.0;
-
- const float GAMEOVER_BMAP_H = 100.0;
-
- extern long random();
- extern void srandom(int seed);
- extern int getpid();
-
- @@implementation TetMatrix
-
- /*
- * Some things should be set differently for color machines for either
- * performances or aesthetic reasons.
- */
- - initForColor
- {
- const NXScreen *deepestScreen;
-
- deepestScreen=[NXApp colorScreen];
-
- if ( deepestScreen->depth == NX_TwoBitGrayDepth ) {
- anm_gameover_delta = 1.0;
- } else {
- anm_gameover_delta = 2.0;
- }
- return self;
- }
-
-
- - initFrame:(const NXRect *)frameRect
- {
- NXSize size, interCell;
- extern BOOL resize(NXSize *aSize);
- float viewWidth, viewHeight;
-
- // Set the # of rows and columns in the view
- [super initFrame:frameRect numRows:TETRIS_ROWS numCols:TETRIS_COLUMNS];
- [self setBackgroundGray:NX_BLACK];
-
- size.width = size.height = 6.0;
- [self setInset:&size];
-
- // Set the amount of space to leave b/w each block
- interCell.width = interCell.height = 1.0; // 1 pixel
- [self setIntercell:&interCell];
-
- pieceVisible = active = NO;
- thePiece = [[Piece alloc] init];
-
- [thePiece getBlockSize:&size];
-
- // Should only resize in Piece.m
- resize(&size); // Make sure block image isn't too large
- [super setElementSize:&size];
-
- // Size Game View.
- // Default view size is (182, 438)
- // Getting (176, 416)
- viewWidth = 6. + TETRIS_COLUMNS * (size.width + interCell.width) + 6.;
- viewHeight = 6. + (TETRIS_ROWS)* (size.height + interCell.height) + 6.;
-
- #ifdef DEBUG
- fprintf(stderr, "Sizing the Tetris view to (%f,%f)\n", viewWidth, viewHeight);
- #endif
- [self sizeTo: viewWidth :viewHeight];
-
- scoreKeeper = nil;
-
- anmBitmap = [[NXImage allocFromZone:[self zone]] initSize:&bounds.size];
-
- // Eventually want the background to be setable
-
- // anmBitmap = [NXImage initSize:&bounds.size];
- // [anmBitmap useFromFile:"Snow.tiff"];
- showNext = nil;
- [self initForColor];
-
- gameRunning = NO;
- srandom(getpid()); // Seed random # generator
-
- return self;
- }
-
- - setupRandomFill:(int)max
- {
- int blockNum;
- int row, col;
-
- if (max > TETRIS_ROWS) max = TETRIS_ROWS;
- if (max > 10) max = 10;
- // fprintf (stderr, "Start random fill ...\n");
- for (row = 0; row < max; row++) {
- for (col = 0; col < TETRIS_COLUMNS; col++) {
- if ((random () & 0x3) == 0) { /* set 1/4 */
- blockNum = (random () & 0x3); // Rand num 0..3
- [super setBitmap: [thePiece getBlockImage:blockNum] at:row :col];
- }
- }
- }
- return self;
- }
-
-
- - (BOOL)acceptsFirstResponder
- {
- return active;
- }
-
- - drawSelf:(const NXRect *)rects :(int)rectCount
- {
- [super drawSelf:rects :rectCount];
- if (pieceVisible) {
- NXRectClip(&insetBounds);
- [thePiece draw:self];
- }
- return self;
- }
-
-
- /*
- * Act upon keyboard input from the user.
- *
- */
- - keyDown:(NXEvent *)theEvent
- {
- unsigned short charCode;
-
- charCode = theEvent->data.key.charCode;
- if (isupper(charCode))
- charCode = tolower(charCode);
-
- switch (charCode) {
- case 'k':
- case '5':
- if (charCode == 'k' || theEvent->flags & NX_NUMERICPADMASK)
- [thePiece turn:self];
- break;
- case 'j':
- case '4':
- if (charCode == 'j' || theEvent->flags & NX_NUMERICPADMASK)
- [thePiece left:self];
- break;
-
- case 'l':
- case '6':
- if (charCode == 'l' || theEvent->flags & NX_NUMERICPADMASK)
- [thePiece right:self];
- break;
-
- case ' ':
- case '2':
- case '0':
- if (charCode == ' ' || theEvent->flags & NX_NUMERICPADMASK) {
- [self stopTimedEntry];
- [thePiece drop:self];
- [self startTimedEntry];
- }
- break;
-
- case 13: // Pause if the user hits return
- [NXApp pause:self];
- }
- return self;
- }
-
-
- - setPieceVisible:(BOOL)flag
- {
- pieceVisible = flag;
- return self;
- }
-
- - setScoreKeeper:keeper
- {
- scoreKeeper = keeper;
- return self;
- }
-
- /*
- * Determine how fast a piece will drop.
- */
- -(double) newDelay
- {
- return 0.5 - 0.1 * sqrt(2.5 * level);
- }
-
- - newGame:(int)theLevel
- {
- [[super setBitmap:nil] display];
- [window makeFirstResponder:self];
- [self setPieceVisible:YES];
- [thePiece reset:self
- piece:((showNext) ? [showNext pieceInfo] : PIECE_INFO_NULL)];
-
- [self setupRandomFill:[randomFields intValue]];
- [self display];
- level = (float)theLevel;
- teDelay = [self newDelay];
- [self startTimedEntry];
- active = YES;
- return self;
- }
-
- - pause:sender
- {
- // Make TetApp the first responder
- [window makeFirstResponder:window];
- // Will making this object the first responder cause problems?
- // [window makeFirstResponder:self];
- active = NO;
- return [self stopTimedEntry];
- }
-
-
- - continue:sender
- {
- active = YES;
- [window makeFirstResponder:self];
- return [self startTimedEntry];
- }
-
- - stop:sender
- {
- active = NO;
- [window makeFirstResponder:window];
- return [self stopTimedEntry];
- }
-
- /*
- * Scroll "Game Over" down the screen after the game is finished.
- */
- - animateGameOver
- {
- NXSize tmpSize;
- id anmGameOver;
- NXRect destRect, unionRect;
-
- tmpSize.height = GAMEOVER_BMAP_H;
- tmpSize.width = insetBounds.size.width;
- anmGameOver = [[NXImage alloc] initSize:&tmpSize];
-
- // Composite "Game Over" to a window
- [anmGameOver lockFocus];
- PSsetalpha(0.0);
- PSrectfill(0.0, 0.0, insetBounds.size.width, GAMEOVER_BMAP_H);
- PSsetalpha(1.0);
- PSgameover(insetBounds.size.width);
- [anmGameOver unlockFocus];
-
- [super getRect:&destRect for:(int)(TETRIS_ROWS / 2) :0];
- [super getRect:&unionRect for:TETRIS_ROWS - 1 :TETRIS_COLUMNS - 1];
- NXUnionRect(&unionRect, &destRect);
-
- [anmBitmap lockFocus];
- [self drawSelf:&destRect :1];
- [anmBitmap unlockFocus];
-
- NXSetRect(&unionRect, destRect.origin.x, unionRect.origin.y,
- destRect.size.width, GAMEOVER_BMAP_H);
- [self lockFocus];
- NXRectClip(&destRect);
-
- while (unionRect.origin.y - anm_gameover_delta >= destRect.origin.y) {
- unionRect.origin.y -= anm_gameover_delta;
-
- [anmGameOver composite:NX_SOVER toPoint:&unionRect.origin];
- [[self window] flushWindow];
- NXPing();
- // Redraw the background to erase the "Game Over" letters
- // [anmBitmap composite:NX_COPY fromRect:&unionRect toPoint:&unionRect.origin];
- [anmBitmap composite:NX_SOVER fromRect:&unionRect toPoint:&unionRect.origin];
- NXPing();
- }
- [anmGameOver composite:NX_SOVER toPoint:&unionRect.origin];
- [self unlockFocus];
-
- [anmGameOver free];
- return self;
- }
-
- /* The following methods:
- * Animate a piece dropping.
- * Dissolve filled rows.
- * Removes filled rows from the game.
- */
-
- - (BOOL) rowFilled:(int)row
- {
- int xc;
-
- for (xc = 0; xc < TETRIS_COLUMNS; xc++)
- if (![super bitmapAt:row :xc])
- break;
- return (xc == TETRIS_COLUMNS);
- }
-
- - (BOOL) rowEmpty:(int) row
- {
- int xc;
-
- for (xc = 0; xc < TETRIS_COLUMNS; xc++)
- if ([super bitmapAt:row :xc])
- break;
- return (xc == TETRIS_COLUMNS);
- }
-
- - fadeFilledRows:(int) from :(int) to
- {
- float gc;
- NXRect destRect;
- NXRect unionRect;
-
- [super getRect:&destRect for:from :0];
- [super getRect:&unionRect for:to :TETRIS_COLUMNS - 1];
- NXUnionRect(&unionRect, &destRect);
-
- // Composite the rows we are about to fade to anmBitmap
- [anmBitmap lockFocus];
- [self drawSelf:&destRect :1];
- [anmBitmap unlockFocus];
-
- // Fade the blocks
- [self lockFocus];
- for (gc = 1.0; gc > 0.3; gc -= .03) {
- PSsetgray(gc);
- PScompositerect(destRect.origin.x, destRect.origin.y, destRect.size.width,
- destRect.size.height, NX_PLUSD);
- [[self window] flushWindow];
- // Now redraw the blocks so we can fade them a little more
- // [anmBitmap composite:NX_COPY fromRect:&destRect toPoint:&destRect.origin];
- [anmBitmap composite:NX_SOVER fromRect:&destRect toPoint:&destRect.origin];
- NXPing();
- }
- // Now make the blocks totally disappear.
- PSsetgray(NX_BLACK);
- PScompositerect(destRect.origin.x, destRect.origin.y, destRect.size.width,
- destRect.size.height, NX_SOVER);
- // destRect.size.height, NX_COPY);
-
- [self unlockFocus];
-
- return self;
- }
-
- /*
- * Move the pieces as they are moved down on the screen after one or more rows
- * has been cleared.
- */
- - animateDrop:(int) firstFullRow :(int)firstNonFullRow :(int) lastNonEmptyRow
- {
- NXPoint dPt;
- NXRect destRect;
- NXRect unionRect;
-
- [super point:&dPt for:firstFullRow :0]; // Place where to put falling blocks
- [super getRect:&destRect for:firstNonFullRow :0]; // First row to move down
- // Last row to move down
- [super getRect:&unionRect for:lastNonEmptyRow :TETRIS_COLUMNS - 1];
-
- // We want to move everything down from the last non-full row to
- // the last row with a piece in it.
-
- NXUnionRect(&unionRect, &destRect);
- unionRect = destRect;
-
- // Create the image of the blocks
- [anmBitmap lockFocus];
- [self drawSelf:&destRect :1];
- [anmBitmap unlockFocus];
-
- [self lockFocus];
-
- PSsetgray(NX_BLACK); // The destination Rect is Black
- PScompositerect(destRect.origin.x, destRect.origin.y, destRect.size.width,
- destRect.size.height, NX_COPY);
-
-
- while (unionRect.origin.y - ANM_DELTA > dPt.y) {
-
- unionRect.origin.y -= ANM_DELTA;
-
- // First clear the window
- [anmBitmap composite:NX_COPY fromRect:&destRect toPoint:&unionRect.origin];
- [[self window] flushWindow];
- PScompositerect(unionRect.origin.x, unionRect.origin.y, unionRect.size.width,
- unionRect.size.height, NX_COPY);
- NXPing();
- }
- [anmBitmap composite:NX_COPY fromRect:&destRect toPoint:&dPt];
- [[self window] flushWindow];
-
- // NXPing();
- [self unlockFocus];
- return self;
- }
-
- /*
- * Remove the filled rows after they have dissolved
- */
- - removeFilledRows
- {
- BOOL filled;
- int ycfrom, ycto, yctop;
- int xc, yc;
- int lastFilledRow, lastNonEmptyRow, firstFilled;
- int piecey = [thePiece getCurRow]; // Get the bottom-most row of the piece.
-
- do {
- filled = NO; // This should only execute once?!?!
-
- // Work our way up from the current piece's row.
- for (ycfrom = piecey; ycfrom < piecey + MAX_SHAPE_SIZE; ycfrom++) {
- if ([self rowFilled: ycfrom]) {
- filled = YES;
- firstFilled = ycfrom;
- break;
- }
- }
-
- if (filled) {
-
- // Find the first row that isn't completely filled.
- lastFilledRow = firstFilled; // Loop can execute 0 times
- for (ycto = firstFilled + 1; ycto < firstFilled + MAX_SHAPE_SIZE; ycto++) {
- if ([self rowFilled: ycto]) {
- lastFilledRow = ycto;
- } else {
- break;
- }
- }
- // Find the topmost row in the program. A row with at least one block.
- // Assert: Must enter loop at least once.
- for (yctop = lastFilledRow+1; yctop < TETRIS_ROWS; yctop++) {
- if (! [self rowEmpty: yctop]) {
- lastNonEmptyRow = yctop; // But do I have to execute this once?
- } else {
- break;
- }
- }
- [self fadeFilledRows: firstFilled :lastFilledRow];
-
- // Animate the all of the pieces as the move down.
- [self animateDrop:firstFilled :lastFilledRow+1 :lastNonEmptyRow];
-
-
- // Move the rows above the faded rows down to take their place.
-
- for (yc = lastFilledRow+1; yc <=lastNonEmptyRow; yc++) {
- for (xc = 0; xc < TETRIS_COLUMNS; xc++) // For each block in the row.
- [super setBitmap:[self bitmapAt:yc :xc] at:firstFilled :xc];
- firstFilled++;
- }
-
- // Clear the rows at the very top that have been moved down
- // and which have nothing to take their place.
-
- for (yc = firstFilled; yc <=lastNonEmptyRow; yc++) {
- #ifdef DEBUG
- printf("Removing row %d\n", yc);
- #endif
- for (xc = 0; xc < TETRIS_COLUMNS; xc++)
- [super setBitmap:nil at:yc :xc];
- }
- piecey++;
- }
- } while (filled);
- return self;
- }
-
-
- /* The main animation routines follow. A timed entry routine is setup
- * so that it calls teHandler at a regular interval (depending on the
- * level)
- */
-
- /*
- * The timed entry handler that gets called every teDelay seconds.
- *
- */
- - step
- {
- static int downWait = 0;
-
- // Move the piece down. If it can't move down make it stick,
- // remove filled rows, and generate a new piece.
-
- if (![thePiece down:self]) {
-
- // After the piece sticks to the bottom, wait for a while before
- // we send the next piece. The wait depends on the current level.
-
- if (++downWait >= level) { // Don't commit the piece immediately
- downWait = 0;
- [self stopTimedEntry];
- [self setPieceVisible:NO];
- [thePiece stick:self]; // Make the piece stick
- [self removeFilledRows];
- [self setPieceVisible:YES];
- if (scoreKeeper) {
- [scoreKeeper addScore:[thePiece points]];
- level += (MAX_LEVEL - level) / 400.0;
- teDelay = [self newDelay];
- }
- // show the next piece.
- if ([thePiece reset:self piece:((showNext) ?
- [showNext pieceInfo] : PIECE_INFO_NULL)])
- [self startTimedEntry];
- else {
- [self animateGameOver];
- [[self window] makeFirstResponder:[self window]];
- active = NO;
- [NXApp gameOver];
- }
- }
-
- } else { // The piece can't go down
- downWait = 0; // Set a delay before showing next piece
- }
- return self;
- }
-
- static void runOneStep (DPSTimedEntry timedEntry, double timeNow, void *data)
- {
- [(id)data step];
- }
-
- - startTimedEntry
- {
- if (!gameRunning) {
- timedEntryNum = DPSAddTimedEntry(teDelay,&runOneStep,
- self, NX_BASETHRESHOLD);
- gameRunning = YES;
- }
- return self;
- }
-
- - stopTimedEntry
- {
- if (gameRunning) {
- DPSRemoveTimedEntry(timedEntryNum);
- gameRunning = NO;
- }
- return self;
- }
-
- /*
- * Clean up.
- */
- - free
- {
- [thePiece free];
- [anmBitmap free];
- return [super free];
- }
-
- @@end
- @
-
-
- 1.7
- log
- @*** empty log message ***
- @
- text
- @d207 2
- a208 1
- [self setupRandomFill:4]; // should be made user selectable
- d219 2
- a220 1
- // [window makeFirstResponder:window];
- d222 1
- a222 1
- [window makeFirstResponder:self];
- @
-
-
- 1.6
- log
- @*** empty log message ***
- @
- text
- @a16 1
- const float ANM_GAMEOVER_DELTA = .0;
- d24 19
- d88 2
- a89 1
- // showNext = nil;
- d97 4
- d102 15
- d171 4
- d207 1
- a215 1
-
- d218 3
- a220 1
- [window makeFirstResponder:window];
- d274 2
- a275 2
- while (unionRect.origin.y - ANM_GAMEOVER_DELTA >= destRect.origin.y) {
- unionRect.origin.y -= ANM_GAMEOVER_DELTA;
- d279 2
- a280 1
- // NXPing();
- d283 1
- a283 1
- // NXPing();
- d515 1
- @
-
-
- 1.5
- log
- @*** empty log message ***
- @
- text
- @d42 6
- a47 1
- [[NXImage findImageNamed:"MonoBlock1"] getSize:&size];
- a61 5
- // Make the Window the proper size
- [[self window] sizeWindow: viewWidth+104. :viewHeight+15.];
-
- pieceVisible = active = NO;
- thePiece = [[Piece alloc] init];
- d238 1
- a238 1
- NXPing();
- @
-
-
- 1.4
- log
- @*** empty log message ***
- @
- text
- @d13 3
- a15 1
- static const float ANM_DELTA = 8.0;// Make it a divisor of the block size
- d17 1
- a17 1
- const float ANM_GAMEOVER_DELTA = 1.0;
- d27 3
- a29 1
- NXSize size;
- d31 1
- a33 4
- [[NXImage findImageNamed:"Block1"] getSize:&size];
- resize(&size); // Make sure image isn't too large
- [self setElementSize:&size];
- [self sizeTo: (10*size.width) +(10) +6. :(25*size.height)+ 10. +6.];
- d39 2
- a40 2
- size.width = size.height = 1.0; // 1 pixel
- [self setIntercell:&size];
- d42 18
- d65 3
- d71 1
- d73 2
- a74 1
- srandom(getpid());
- d94 5
- a137 1
-
- d247 1
- a247 1
- /* The following methods
- @
-
-
- 1.3
- log
- @*** empty log message ***
- @
- text
- @d30 1
- d32 1
- d47 1
- a47 1
- [anmBitmap useFromFile:"Snow.tiff"];
- a53 8
- /*
- * Tell the Piece object about the Cheater object
- */
- - setCheater:anObject
- {
- [thePiece setCheater: anObject]; // Just pass it on.
- return self;
- }
- d109 1
- d208 1
- a208 1
- [anmBitmap composite:NX_COPY fromRect:&unionRect toPoint:&unionRect.origin];
- d210 1
- a210 1
- // NXPing();
- d255 1
- d260 1
- d267 1
- d272 1
- d293 3
- a295 2
- [super point:&dPt for:firstFullRow :0];
- [super getRect:&destRect for:firstNonFullRow :0];
- d304 1
- d310 1
- a310 1
- //#ifdef FOO
- a313 1
- //#endif
- d315 1
- d317 1
- d369 1
- d373 1
- a373 1
- lastNonEmptyRow = yctop;
- a401 2
- // [self display:&destRect :1];
- // NXPing();
- @
-
-
- 1.2
- log
- @Tetris 1.2
- @
- text
- @a0 1
-
- d12 4
- a15 3
- #define ANM_DELTA 8.0
- #define GAMEOVER_BMAP_H 100.0
- #define ANM_GAMEOVER_DELTA 1.0
- d26 1
- a26 1
-
- d31 1
- d34 3
- a36 1
- size.width = size.height = 1.0;
- d38 1
- a41 1
- anmBitmap = [NXImage newSize:&bounds.size];
- d43 5
- a47 3
- showNext = nil;
- teRunning = NO;
- colorWindow = [window canStoreColor];
- d52 9
- a78 2
- BOOL abc=YES;
- NXWindowDepth depth;
- a79 3
- abc = [window canStoreColor];
- depth = [window depthLimit];
-
- d130 1
- a130 1
- -(double) newDelay:(float) level
- d144 1
- a144 1
- teDelay = [self newDelay:level];
- d180 1
- a180 1
- NXRect dRect, uRect;
- d194 4
- a197 3
- [self getRect:&dRect for:(int)(TETRIS_ROWS / 2) :0];
- [self getRect:&uRect for:TETRIS_ROWS - 1 :TETRIS_COLUMNS - 1];
- NXUnionRect(&uRect, &dRect);
- d199 1
- a199 1
- [self drawSelf:&dRect :1];
- d202 2
- a203 2
- NXSetRect(&uRect, dRect.origin.x, uRect.origin.y,
- dRect.size.width, GAMEOVER_BMAP_H);
- d205 6
- a210 4
- NXRectClip(&dRect);
- while (uRect.origin.y - ANM_GAMEOVER_DELTA >= dRect.origin.y) {
- uRect.origin.y -= ANM_GAMEOVER_DELTA;
- [anmGameOver composite:NX_SOVER toPoint:&uRect.origin];
- d212 4
- a215 2
- NXPing();
- [anmBitmap composite:NX_COPY fromRect:&uRect toPoint:&uRect.origin];
- d217 1
- a217 1
- [anmGameOver composite:NX_SOVER toPoint:&uRect.origin];
- d225 3
- a227 3
- * animate a piece dropping
- * dissolve filled rows
- * removes filled rows from the game.
- d230 1
- a230 1
- static BOOL rowFilled(id self, int row)
- d235 1
- a235 1
- if (![self bitmapAt:row :xc])
- d240 1
- a240 1
- static BOOL rowEmpty(id self, int row)
- d243 1
- a243 1
-
- d245 1
- a245 1
- if ([self bitmapAt:row :xc])
- d253 2
- a254 2
- NXRect dRect;
- NXRect uRect;
- d256 8
- a263 8
- [self getRect:&dRect for:from :0];
- [self getRect:&uRect for:to :TETRIS_COLUMNS - 1];
- NXUnionRect(&uRect, &dRect);
-
- [self->anmBitmap lockFocus];
- [self drawSelf:&dRect :1];
- [self->anmBitmap unlockFocus];
-
- d267 5
- a271 4
- PScompositerect(dRect.origin.x, dRect.origin.y, dRect.size.width,
- dRect.size.height, NX_PLUSD);
- [self->window flushWindow];
- [self->anmBitmap composite:NX_COPY fromRect:&dRect toPoint:&dRect.origin];
- d275 4
- a278 2
- PScompositerect(dRect.origin.x, dRect.origin.y, dRect.size.width,
- dRect.size.height, NX_COPY);
- d280 1
- d284 5
- a288 1
- - animateDrop:(int) from :(int)to :(int) top
- d291 2
- a292 8
- NXRect dRect;
- NXRect uRect;
-
- [self point:&dPt for:from :0];
- [self getRect:&dRect for:to :0];
- [self getRect:&uRect for:top :TETRIS_COLUMNS - 1];
- NXUnionRect(&uRect, &dRect);
- uRect = dRect;
- d294 10
- d305 1
- a305 1
- [self drawSelf:&dRect :1];
- d307 1
- a307 1
-
- d309 11
- a319 6
- PSsetgray(NX_BLACK);
- PScompositerect(dRect.origin.x, dRect.origin.y, dRect.size.width,
- dRect.size.height, NX_COPY);
- while (uRect.origin.y - ANM_DELTA > dPt.y) {
- uRect.origin.y -= ANM_DELTA;
- [anmBitmap composite:NX_COPY fromRect:&dRect toPoint:&uRect.origin];
- d321 2
- a322 2
- PScompositerect(uRect.origin.x, uRect.origin.y, uRect.size.width,
- uRect.size.height, NX_COPY);
- d325 1
- a325 1
- [anmBitmap composite:NX_COPY fromRect:&dRect toPoint:&dPt];
- d341 3
- a343 2
- int piecey = [thePiece y];
-
- d345 11
- a355 6
- filled = NO;
- for (ycfrom = piecey; ycfrom < piecey + MAX_SHAPE_SIZE; ycfrom++)
- if (rowFilled(self, ycfrom)) {
- filled = YES;
- break;
- }
- a356 12
- for (ycto = ycfrom + 1; ycto < ycfrom + MAX_SHAPE_SIZE; ycto++)
- if (!rowFilled(self, ycto))
- break;
- for (yctop = ycto; yctop < TETRIS_ROWS; yctop++)
- if (rowEmpty(self, yctop))
- break;
-
- [self fadeFilledRows: ycfrom :ycto - 1];
- [self animateDrop:ycfrom :ycto :yctop - 1];
- // [self getRect:&uRect for:ycfrom :0];
- // [self getRect:&dRect for:yctop :TETRIS_COLUMNS - 1];
- // NXUnionRect(&uRect, &dRect);
- d358 38
- a395 1
- for (yc = ycto; yc < yctop; yc++) {
- d397 1
- a397 2
- [super setBitmap:[self bitmapAt:yc :xc] at:ycfrom :xc];
- ycfrom++;
- d399 2
- a400 6
- for (yc = ycfrom; yc < yctop; yc++)
- for (xc = 0; xc < TETRIS_COLUMNS; xc++)
- [super setBitmap:nil at:yc :xc];
-
- // [self display:&dRect :1];
- // NXPing();
- d420 4
- a423 1
-
- d429 1
- a429 1
- if (++downWait >= level) {
- d433 1
- a433 1
- [thePiece stick:self];
- d439 1
- a439 1
- teDelay = [self newDelay: level];
- d451 3
- a453 2
- } else { // The piece can go down
- downWait = 0;
- a462 1
-
- d465 4
- a468 3
- if (!teRunning) {
- timedEntryNum = DPSAddTimedEntry(teDelay,&runOneStep,self, NX_BASETHRESHOLD);
- teRunning = YES;
- d475 1
- a475 1
- if (teRunning) {
- d477 1
- a477 1
- teRunning = NO;
- @
-
-
- 1.1
- log
- @Initial revision
- @
- text
- @d6 1
- d36 1
- a36 1
- thePiece = [Piece new];
- d42 1
- a42 1
-
- d65 2
- d68 3
- d105 111
- d236 1
- a236 1
- static void fadeFilledRows(id self, int from, int to)
- d263 1
- d266 1
- a266 1
- static void animateDrop(id self, int from, int to, int top)
- a267 1
- NXCoord yc;
- d277 2
- a278 2
-
- [self->anmBitmap lockFocus];
- d280 1
- a280 1
- [self->anmBitmap unlockFocus];
- d288 2
- a289 2
- [self->anmBitmap composite:NX_COPY fromRect:&dRect toPoint:&uRect.origin];
- [self->window flushWindow];
- d294 2
- a295 2
- [self->anmBitmap composite:NX_COPY fromRect:&dRect toPoint:&dPt];
- [self->window flushWindow];
- d299 1
- d302 3
- a304 1
-
- a310 2
- NXRect dRect;
- NXRect uRect;
- d327 2
- a328 2
- fadeFilledRows(self, ycfrom, ycto - 1);
- animateDrop(self, ycfrom, ycto, yctop - 1);
- d335 1
- a335 1
- [self setBitmap:[self bitmapAt:yc :xc] at:ycfrom :xc];
- d340 1
- a340 1
- [self setBitmap:nil at:yc :xc];
- a349 5
- - setPieceVisible:(BOOL)flag
- {
- pieceVisible = flag;
- return self;
- }
- d351 4
- a354 5
- - setScoreKeeper:keeper
- {
- scoreKeeper = keeper;
- return self;
- }
- d356 5
- a360 1
- double newDelay(float level)
- d362 1
- a362 44
- return 0.5 - 0.1 * sqrt(2.5 * level);
- }
-
- - newGame:(int)theLevel
- {
- [[self setBitmap:nil] display];
- [window makeFirstResponder:self];
- [self setPieceVisible:YES];
- [thePiece reset:self
- piece:((showNext) ? [showNext pieceInfo] : PIECE_INFO_NULL)];
- [self display];
- level = (float)theLevel;
- teDelay = newDelay(level);
- [self startTimedEntry];
- active = YES;
- return self;
- }
-
-
- - pause:sender
- {
- [window makeFirstResponder:window];
- active = NO;
- return [self stopTimedEntry];
- }
-
-
- - continue:sender
- {
- active = YES;
- [window makeFirstResponder:self];
- return [self startTimedEntry];
- }
-
- - stop:sender
- {
- active = NO;
- [window makeFirstResponder:window];
- return [self stopTimedEntry];
- }
- #ifdef FOO
- static id newBitmap()
- {
- char *bitmapName;
- d364 1
- a364 16
- switch (random() % NUM_BITMAPS) {
- case 0:
- bitmapName = "Block1";
- break;
- case 1:
- bitmapName = "Block2";
- break;
- case 2:
- bitmapName = "Block3";
- break;
- default:
- bitmapName = "Block4";
- }
- return [NXImage findImageNamed:bitmapName];
- }
- #endif
- d366 2
- a367 9
- static void animateGameOver(id self)
- {
- NXSize tmpSize;
- id anmGameOver;
- NXRect dRect, uRect;
-
- tmpSize.height = GAMEOVER_BMAP_H;
- tmpSize.width = self->insetBounds.size.width;
- anmGameOver = [[NXImage alloc] initSize:&tmpSize];
- d369 1
- a369 39
- // Composite "Game Over" to a window
- [anmGameOver lockFocus];
- PSsetalpha(0.0);
- PSrectfill(0.0, 0.0, self->insetBounds.size.width, GAMEOVER_BMAP_H);
- PSsetalpha(1.0);
- PSgameover(self->insetBounds.size.width);
- [anmGameOver unlockFocus];
-
- [self getRect:&dRect for:(int)(TETRIS_ROWS / 2) :0];
- [self getRect:&uRect for:TETRIS_ROWS - 1 :TETRIS_COLUMNS - 1];
- NXUnionRect(&uRect, &dRect);
- [self->anmBitmap lockFocus];
- [self drawSelf:&dRect :1];
- [self->anmBitmap unlockFocus];
-
- NXSetRect(&uRect, dRect.origin.x, uRect.origin.y,
- dRect.size.width, GAMEOVER_BMAP_H);
- [self lockFocus];
- NXRectClip(&dRect);
- while (uRect.origin.y - ANM_GAMEOVER_DELTA >= dRect.origin.y) {
- uRect.origin.y -= ANM_GAMEOVER_DELTA;
- [anmGameOver composite:NX_SOVER toPoint:&uRect.origin];
- [self->window flushWindow];
- NXPing();
- [self->anmBitmap composite:NX_COPY fromRect:&uRect toPoint:&uRect.origin];
- }
- [anmGameOver composite:NX_SOVER toPoint:&uRect.origin];
- [self unlockFocus];
-
- [anmGameOver free];
- }
-
- void teHandler(DPSTimedEntry teNum, double now, id self)
- {
- id thePiece = self->thePiece;
- static int downWait = 0;
-
- if (![thePiece down:self]) {
- if (++downWait >= self->level) {
- d376 4
- a379 4
- if (self->scoreKeeper) {
- [self->scoreKeeper addScore:[thePiece points]];
- self->level += (MAX_LEVEL - self->level) / 400.0;
- self->teDelay = newDelay(self->level);
- d381 2
- a382 2
- if ([thePiece reset:self piece:((self->showNext) ?
- [self->showNext pieceInfo] : PIECE_INFO_NULL)])
- d385 3
- a387 3
- animateGameOver(self);
- [self->window makeFirstResponder:self->window];
- self->active = NO;
- d391 4
- a394 2
- } else
- downWait = 0;
- d397 6
- d405 5
- a409 6
- if (!teRunning) {
- timedEntryNum = DPSAddTimedEntry(teDelay, (DPSTimedEntryProc)teHandler,
- self, NX_BASETHRESHOLD);
- teRunning = YES;
- }
- return self;
- d421 3
- @
-